home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-04 / bipl.zip / PROGS.ZIP / CROSS.ICN < prev    next >
Text File  |  1992-09-28  |  5KB  |  193 lines

  1. ############################################################################
  2. #
  3. #    File:     cross.icn
  4. #
  5. #    Subject:  Program to display intersection of words
  6. #
  7. #    Author:   William P. Malloy
  8. #
  9. #    Date:     June 10, 1988
  10. #
  11. ###########################################################################
  12. #  
  13. #     This program takes a list of words and tries to arrange them
  14. #  in cross-word format so that they intersect. Uppercase letters
  15. #  are mapped into lowercase letters on input.  For example, the
  16. #  input
  17. #  
  18. #          and
  19. #          eggplants
  20. #          elephants
  21. #          purple
  22. #  
  23. #  produces the output
  24. #       +---------+
  25. #       | p       |
  26. #       | u e     |
  27. #       | r g     |
  28. #       | p g     |
  29. #       |elephants|
  30. #       | e l     |
  31. #       |   and   |
  32. #       |   n     |
  33. #       |   t     |
  34. #       |   s     |
  35. #       +---------+
  36. #  
  37. #  Diagnostics: The program objects if the input contains a nonal-
  38. #  phabetic character.
  39. #  
  40. #  Comments: This program produces only one possible intersection
  41. #  and it does not attempt to produce the most compact result.  The
  42. #  program is not very fast, either.  There is a lot of room for
  43. #  improvement here. In particular, it is natural for Icon to gen-
  44. #  erate a sequence of solutions.
  45. #  
  46. ############################################################################
  47.  
  48. global fast, place, array, csave, fsave, number
  49.  
  50. procedure main()
  51.    local words, nonletter, line
  52.    nonletter := ~&letters
  53.    words := []
  54.  
  55.    while line := map(read()) do
  56.       if upto(nonletter,line) then stop("input contains nonletter")
  57.       else put(words,line)
  58.    number := *words
  59.    kross(words)
  60.  
  61. end
  62.  
  63. procedure kross(words)
  64.    local one, tst, t
  65.    array := [get(words)]
  66.    t := 0
  67.    while one := get(words) do {
  68.       tst := *words
  69.       if fit(one,array,0 | 1) then
  70.      t := 0
  71.       else {
  72.      t +:= 1
  73.          put(words,one)
  74.      if t > tst then
  75.         break
  76.      }
  77.       }
  78.    if *words = 0 then Print(array)
  79.    else write(&errout,"cannot construct puzzle")
  80. end
  81.  
  82. procedure fit(word,matrix,where)
  83.    local i, j, k, l, one, test, t, s
  84.    s := *matrix
  85.    t := *matrix[1]
  86.    every k := gen(*word) do
  87.       every i := gen(s) do
  88.          every j := gen(t) do
  89.         if matrix[i][j] == word[k] then {
  90.                # test for vertical fit
  91.                if where = 0 then {
  92.                   test := 0
  93.                   every l := (i - k + 1) to (i + (*word - k)) do
  94.                      if tstv(matrix,i,j,l,s,t) then {
  95.                         test := 1
  96.                         break
  97.                         }
  98.                   if test = 0 then
  99.                      return putvert(matrix,word,i,j,k)
  100.                   }
  101.                if where = 1 then {
  102.                   test := 0
  103.                   every l := (j - k + 1) to (j + (*word - k)) do
  104.                      if tsth(matrix,i,j,l,s,t) then {
  105.                         test := 1
  106.                         break
  107.                         }
  108.                   if test = 0 then
  109.                      return puthoriz(matrix,word,i,j,k)
  110.                   }
  111.                }
  112. end
  113.  
  114. procedure tstv(matrix,i,j,l,s,t)
  115.    return ((matrix[(l ~= i) & (s >= l) & (0 < l)][0 < j-1] ~== " ") |
  116.       (matrix[(l ~= i) & (s >= l) & (0 < l)][t >= j + 1] ~== " ") |
  117.       (matrix[(i ~= l-1) & (s >= l-1) & (0 < l-1)][j] ~== " ") |
  118.       (matrix[(i ~= l + 1) & (s >= l+1) & (0 < l + 1)][j] ~== " ") |
  119.       (matrix[(l ~= i) & (s >= l) & (0 < l)][j] ~== " "))
  120. end
  121.  
  122. procedure tsth(matrix,i,j,l,s,t)
  123.    return ((matrix[0 < i-1][(l ~= j) & (t >= l) & (0 < l)] ~== " ") |
  124.       (matrix[s >= i + 1][(l ~= j) & (t >= l) & (0 < l)] ~== " ") |
  125.       (matrix[i][(j ~= l-1) & (t >= l-1) & (0 < l-1)] ~== " ") |
  126.       (matrix[i][(j ~= l + 1) & (t >= l + 1) & (0 < l + 1)] ~== " ") |
  127.       (matrix[i][(l ~= j) & (t >= l) & (0 < l)] ~== " "))
  128. end
  129.  
  130. procedure gen(i)
  131.    local tmp, up, down
  132.    tmp := i / 2
  133.    if (i % 2) = 1 then
  134.       tmp +:= 1
  135.    suspend tmp
  136.    up := tmp
  137.    down := tmp
  138.    while (up < i) do {
  139.       suspend up +:= 1
  140.       suspend (down > 1) & (down -:= 1)
  141.       }
  142. end
  143.  
  144. # put `word' in vertically at pos(i,j)
  145.  
  146. procedure putvert(matrix,word,i,j,k)
  147.    local hdim, vdim, up, down, l, m, n
  148.    vdim := *matrix
  149.    hdim := *matrix[1]
  150.    up := 0
  151.    down := 0
  152.    up := abs(0 > (i - k))
  153.    down := abs(0 > ((vdim - i) - (*word - k)))
  154.    every m := 1 to up do
  155.       push(matrix,repl(" ",hdim))
  156.    i +:= up
  157.    every m := 1 to down do
  158.       put(matrix,repl(" ",hdim))
  159.    every l := 1 to *word do
  160.       matrix[i + l - k][j] := word[l]
  161.    return matrix
  162. end
  163.  
  164. # put `word' in horizontally at position i,j in matrix
  165.  
  166. procedure puthoriz(matrix,word,i,j,k)
  167.    local hdim, vdim, left, right, l, m, n
  168.    vdim := *matrix
  169.    hdim := *matrix[1]
  170.    left := 0
  171.    right := 0
  172.    left := (abs(0 > (j - k))) | 0
  173.    right := (abs(0 > ((hdim - j) - (*word - k)))) | 0
  174.    every m := 1 to left do
  175.       every l := 1 to vdim do
  176.        matrix[l] := " " || matrix[l]
  177.    j +:= left
  178.    every m := 1 to right do
  179.       every l := 1 to vdim do
  180.       matrix[l] ||:= " "
  181.    every l := 1 to *word do
  182.       matrix[i][j + l - k] := word[l]
  183.    return matrix
  184. end
  185.  
  186. procedure Print(matrix)
  187.    local i
  188.    write("+",repl("-",*matrix[1]),"+")
  189.    every i := 1 to *matrix do
  190.       write("|",matrix[i],"|")
  191.    write("+",repl("-",*matrix[1]),"+")
  192. end
  193.